package cn.glc.daily.life.config.advice;

import cn.glc.daily.life.common.exceptions.CustomMethodArgumentNotValidException;
import cn.glc.daily.life.common.exceptions.GlobalException;
import cn.glc.daily.life.common.utils.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.stream.Collectors;

import static cn.glc.daily.life.common.enums.GlobalCodeEnum.BusinessExceptionEnum.UNAUTHORIZED_ERROR;
import static cn.glc.daily.life.common.enums.GlobalCodeEnum.HttpStatusEnum.FAIL;


/**
 * 全局对外统一返回异常
 *
 * @author simon
 * @date 2020/6/2 10:56
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
    /**
     * 定制化异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(GlobalException.class)
    public JsonResult globalExceptionAdvice(GlobalException exception) {
        JsonResult jsonResult = JsonResult.returnFailure(exception.getCode(), exception.getMsg());
        return jsonResult == null ? JsonResult.returnFailure() : jsonResult;
    }

    /**
     * Valid 自定义注解异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public JsonResult methodArgumentNotValidExceptionAdvice(MethodArgumentNotValidException exception) {
        CustomMethodArgumentNotValidException customMethodArgumentNotValidException = new CustomMethodArgumentNotValidException(exception.getParameter(), exception.getBindingResult());
        JsonResult jsonResult = JsonResult.returnFailure(FAIL.getCode(), customMethodArgumentNotValidException.getMessage());
        return jsonResult;
    }

    /**
     * shiro 相关异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(AuthenticationException.class)
    public JsonResult authenticationExceptionAdvice(AuthenticationException exception) {
        String message = exception.getMessage();
        JsonResult jsonResult = JsonResult.returnFailure(FAIL.getCode(), message);
        return jsonResult;
    }

    /**
     * shiro 相关异常(授权authz)
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(UnauthorizedException.class)
    public JsonResult authenticationExceptionAdvice(UnauthorizedException exception) {
        return JsonResult.returnFailure(UNAUTHORIZED_ERROR);
    }

    /**
     * 参数绑定异常
     * 1. 登录类型错误
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(BindException.class)
    public JsonResult bindException(BindException exception) {
        String errorList = exception.getBindingResult().getFieldErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(","));
        return JsonResult.returnCustomFailure(errorList);
    }

    /**
     * 其他所有异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    public JsonResult exceptionAdvice(Exception exception) {
        //其他类型的错误,打印堆栈信息至控制台
        exception.printStackTrace();
        log.error("拦截异常:{}", exception.getMessage());
        JsonResult jsonResult = JsonResult.returnFailure(FAIL.getCode(), exception.getMessage());
        return jsonResult;
    }
}
